package com.ll.domain.user.base.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ll.base.dto.NameDTO;
import com.ll.base.enums.ResultCodeEnum;
import com.ll.base.exception.CustomRunTimeException;
import com.ll.base.util.ListUtil;
import com.ll.base.util.ScalarUtil;
import com.ll.domain.tenant.enums.AppEnum;
import com.ll.domain.tenant.enums.SystemOSEnum;
import com.ll.domain.user.base.UserBaseService;
import com.ll.domain.user.convert.UserConvert;
import com.ll.dal.mapper.UserMapper;
import com.ll.dal.po.UserPO;
import com.ll.domain.user.dto.UserDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserBaseServiceImpl extends ServiceImpl<UserMapper, UserPO> implements UserBaseService {

    private final UserMapper userMapper;

    @Override
    public Long register(UserDTO userDTO) {
        UserDTO user = this.getByDingUserId(userDTO.getDingTalkUserId());
        if (user == null) {
            UserPO userPO = UserConvert.DTO2PO(userDTO);
            userMapper.insert(userPO);
            userDTO.setId(userPO.getId());
        }else{
            userDTO.setId(user.getId());
            userDTO.setLogo(user.getLogo());
            userDTO.setIntegral(user.getIntegral());
            UserPO userPO = new UserPO();
            userPO.setId(user.getId());
            userPO.setRoles(JSONObject.toJSONString(userDTO.getRoles()));
            userMapper.updateById(userPO);
        }
        return userDTO.getId();
    }

    @Override
    public List<Long> batchInit(List<UserDTO> list) {
        List<String> dingUserIds = ListUtil.toList(list, UserDTO::getDingTalkUserId);
        List<UserPO> userPOS = this.getByDingUserIds(dingUserIds);
        List<String> existDingUserIds = ListUtil.toList(userPOS, UserPO::getDingUserId);
        List<UserPO> pos = list.stream()
                .filter(r -> !existDingUserIds.contains(r.getDingTalkUserId()))
                .map(UserConvert::DTO2PO)
                .collect(Collectors.toList());
        this.saveBatch(pos);
        return ListUtil.toList(pos, UserPO::getId);
    }


    @Override
    public List<UserDTO> getByName(NameDTO dto) {
        List<UserPO> userPOS = userMapper.selectList(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getName, dto.getName())
        );
        return ListUtil.toList(userPOS, UserConvert::PO2DTO);
    }

    @Override
    public List<UserDTO> getByIds(List<Long> ids) {
        List<UserPO> userPOS = userMapper.selectList(new LambdaQueryWrapper<UserPO>()
                .in(UserPO::getId, ids)
        );
        return ListUtil.toList(userPOS, UserConvert::PO2DTO);
    }

    @Override
    public Long getIntegralRanking(Long tenantId, Long uid) {
        return userMapper.getRanking(tenantId, uid);
    }


    @Override
    public UserDTO getByWechatUIdAndAppId(Long tenantId, AppEnum app, String wechatUserId, boolean isCheckNull) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getWechatUserId, wechatUserId)
                .eq(UserPO::getAppId, app)
                .eq(UserPO::getTenantId, tenantId)
        );
        CustomRunTimeException.conditionCheckNull(isCheckNull, userPO, "User");
        return UserConvert.PO2DTO(userPO);
    }


    @Override
    public List<UserDTO> getByDingUids(List<String> dingUids) {
        List<UserPO> byDingUserIds = this.getByDingUserIds(dingUids);
        return ListUtil.toList(byDingUserIds, UserConvert::PO2DTO);
    }

    @Override
    public void addIntegral(Long id, Integer integral) {
        this.updateIntegral(this.getById(id, true), integral);
    }

    @Override
    public void checkIntegral(List<Long> ids, Integer integral) {
        List<UserPO> userPOS = userMapper.selectList(new LambdaQueryWrapper<UserPO>()
                .in(UserPO::getId, ids)
                .lt(UserPO::getIntegral, integral));
        if (ScalarUtil.isNotEmpty(userPOS)) {
            throw new CustomRunTimeException(ResultCodeEnum.INTEGRAL_ERROR);
        }
    }

    @Override
    public void addIntegral(String dingUserId, Integer integral) {
        UserDTO dto = this.getByDingUserId(dingUserId);
        this.updateIntegral(dto, integral);
    }

    @Override
    public void updateIntegral(UserDTO po, Integer integral) {
        UserPO userPO = new UserPO();
        userPO.setId(po.getId());
        integral = po.getIntegral() + integral;
        integral = integral < 0 ? 0 : integral;
        userPO.setIntegral(integral);
        userMapper.updateById(userPO);
    }

    @Override
    public UserDTO getById(Long tenantId, Long id, boolean checkNull) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getTenantId, tenantId)
                .eq(UserPO::getId, id));
        if (checkNull) {
            CustomRunTimeException.checkNull(userPO, "UserPO");
        }
        return UserConvert.PO2DTO(userPO);
    }


    @Override
    public UserDTO getById(Long id, boolean checkNull) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getId, id));
        if (checkNull) {
            CustomRunTimeException.checkNull(userPO, "UserPO");
        }
        return UserConvert.PO2DTO(userPO);
    }

    @Override
    public UserDTO getByDingUserId(String dingUserId) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getDingUserId, dingUserId));
        return UserConvert.PO2DTO(userPO);
    }

    public List<UserPO> getByDingUserIds(List<String> dingUserIds) {
        return userMapper.selectList(new LambdaQueryWrapper<UserPO>()
                .in(UserPO::getDingUserId, dingUserIds));
    }
}
